#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QTime>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <map>
#include <vector>
#include <memory>
#include <QFile>

// 小工具：从一条完整消息(QByteArray)里“只解析出JSON与type”
// 协议: [4B le json_len][json][...optional binary...]
static inline bool peekTypeFromMessage(const QByteArray& bytes, int& typeOut, nlohmann::json& jOut) {
    typeOut = 0;
    if (bytes.size() < 4) return false;

    // 读小端长度
    uint32_t json_len = 0;
    std::memcpy(&json_len, bytes.constData(), 4);
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
    json_len = __builtin_bswap32(json_len);
#endif
    if (json_len == 0 || json_len > 100*1024) return false;
    if (bytes.size() < 4 + (int)json_len) return false;

    const char* json_ptr = bytes.constData() + 4;
    try {
        jOut = nlohmann::json::parse(std::string(json_ptr, json_ptr + json_len));
    } catch (...) { return false; }

    typeOut = jOut.value("type", 0);
    return true;
}


std::map<int, QString> positionMapS = {
    {0, "下"} ,
    {1, "左下"},
    {2, "左"},
    {3, "左上"},
    {4, "上"},
    {5, "右上"},
    {6, "右"},
    {7, "右下"},
    {8, "停止"}
};

std::map<int, std::string> positionMap = {
    {0, "d"},  // 下
    {1, "3"},  // 左下（用 "3" 代替）
    {2, "l"},  // 左
    {3, "1"},  // 左上（用 "1" 代替）
    {4, "u"},  // 上
    {5, "2"},  // 右上（用 "2" 代替）
    {6, "r"},  // 右
    {7, "4"},  // 右下（用 "4" 代替）
    {8, "s"}   // 停止转动
};


MainWindow::MainWindow(xdgTcpClient *client, QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWindow)
    , m_client(client)              // 控制面连接（仍在 UI 线程）
    , m_videoClient(nullptr)        // 视频专线（放到 I/O 线程）
    , m_playerCore(nullptr)
    , m_Channel_1_isPlay(false)
{
    ui->setupUi(this);

    // --- 1) 基础 UI 设置 ---
    this->setWindowIcon(QIcon(":/img/camera.png")); // 设置窗口图标
    this->setFont(g_font);
    ui->videoLabel1->setScaledContents(true); // // 让 QLabel 始终按自身控件大小缩放像素
    ui->videoLabel1->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // // 忽略 sizeHint（图片原始尺寸），完全由布局/父控件决定大小
    setTreeWidgetData(); // 设置树形框数据
    ui->windowInfoTable->setColumnCount(2); // 设置窗口消息列数
    ui->windowInfoTable->setRowCount(100); // 设置窗口消息行数
    ui->windowInfoTable->setHorizontalHeaderLabels(QStringList() << "时间" << "消息"); // 设置水平表头
    connect(ui->widget_GaugeCloud, &GaugeCloud::mousePressed, this, &MainWindow::ptzControl); // 连接云台控制信号

    // --- 2) 用户操作TCP仍复用同一条连接 ---
    if (m_client) {
        connect(m_client, &xdgTcpClient::connected,    this, &MainWindow::onClientConnected);
        connect(m_client, &xdgTcpClient::disconnected, this, &MainWindow::onClientDisconnected);
        connect(m_client, &xdgTcpClient::messageReceived, this, &MainWindow::onMessageReceived);
        connect(m_client, &xdgTcpClient::errorOccurred, this, &MainWindow::onErrorOccurred);
        if (m_client->isConnected()) onClientConnected();
    }

    // --- 3) 视频流专用TCP与AVPacket解析的线程与对象创建：无 parent，再 moveToThread ---
    m_ioThread = new QThread(this);
    m_decodeThread = new QThread(this);

    m_videoClient = new xdgTcpClient();                  // 无 parent，否则无法 moveToThread
    m_parser      = new xclient::VideoStreamParser();    // 无 parent

    m_videoClient->moveToThread(m_ioThread);
    m_parser->moveToThread(m_decodeThread);

    // --- 4) 线程收尾：程序退出时优雅结束，线程结束时清理对象 ---
    connect(qApp, &QCoreApplication::aboutToQuit, this, [=](){
        // 先请求网络侧断开（在 I/O 线程中执行）
        QMetaObject::invokeMethod(m_videoClient, "disconnectFromServer", Qt::QueuedConnection);
        m_ioThread->quit();
        m_decodeThread->quit();
        m_ioThread->wait(1000);
        m_decodeThread->wait(1000);
    });
    connect(m_ioThread,     &QThread::finished, m_videoClient,   &QObject::deleteLater);
    connect(m_decodeThread, &QThread::finished, m_parser,        &QObject::deleteLater);
    connect(m_ioThread,     &QThread::finished, m_ioThread,      &QObject::deleteLater);
    connect(m_decodeThread, &QThread::finished, m_decodeThread,  &QObject::deleteLater);

    // --- 5) 解析器 -> UI：帧到就显示（跨线程自动 Queued） ---
    connect(m_parser, &xclient::VideoStreamParser::frameReady, this,
            [this](const QImage& img, double){
                m_lastFrame = img; // 如需 RGB32：m_lastFrame = img.convertToFormat(QImage::Format_RGB32);
                if (ui->videoLabel1) {
                    ui->videoLabel1->setPixmap(QPixmap::fromImage(m_lastFrame));
                }
            });

    connect(m_parser, &xclient::VideoStreamParser::errorOccurred, this,
            [this](const QString& e){ insertMsg(QString("[视频流解析] %1").arg(e)); });

    // --- 6) I/O -> 解析：只把 type==106 的完整消息喂给视频解析器 ---
    connect(m_videoClient, &xdgTcpClient::messageReceived,
            m_parser, [this](const QByteArray& bytes){
                int type = 0; nlohmann::json j;
                if (!peekTypeFromMessage(bytes, type, j)) {
                    qWarning() << "[Dispatcher] invalid message";
                    return;
                }
                if (type == 106) {
                    m_parser->feed(bytes);     // 在解码线程执行
                } else {
                     // 非视频类型
                }
            },
            Qt::QueuedConnection); // 明确使用队列连接，保护 I/O 线程

    // --- 7) 连接/断开通知（I/O -> UI），并在连上后 reset 解析器以等待关键帧 ---
    connect(m_videoClient, &xdgTcpClient::connected, this, [this](){
        setWindowTitle("灵眸 --- 视频流服务器连接成功");
        if (m_parser) QMetaObject::invokeMethod(m_parser, "reset", Qt::QueuedConnection);
    }, Qt::QueuedConnection);

    connect(m_videoClient, &xdgTcpClient::disconnected, this, [this](){
        if (m_parser) QMetaObject::invokeMethod(m_parser, "reset", Qt::QueuedConnection);
        m_lastFrame = QImage();
        if (ui->videoLabel1) ui->videoLabel1->clear();
    }, Qt::QueuedConnection);

    // 启动线程
    m_ioThread->start();
    m_decodeThread->start();

    // --- 8) 发起连接：必须在 I/O 线程调用 ---
    QMetaObject::invokeMethod(m_videoClient, [this](){
        m_videoClient->connectToServer("192.168.233.135", 8080);
    }, Qt::QueuedConnection);

    // m_playerCore = new xdgVLC(this);
}


MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setTreeWidgetData()
{
    // 树形框设置水平头（顶层）
    ui->deviceTreeWidget->setHeaderLabel ("默认分组");


    // 设置树形部件项目（顶层子节点）
    QTreeWidgetItem *netVideo = new QTreeWidgetItem(QStringList() << "网络视频");
    ui->deviceTreeWidget->addTopLevelItem(netVideo); // 加载顶层的子节点到顶层

    // 顶层子节点的子节点
    QTreeWidgetItem *child1 = new QTreeWidgetItem( QStringList() << "网络视频1" );
    netVideo->addChild(child1);
    QTreeWidgetItem *child2 = new QTreeWidgetItem( QStringList() << "网络视频2" );
    netVideo->addChild(child2);

    // 顶层子节点的子节点的子节点
    QTreeWidgetItem *child11 = new QTreeWidgetItem( QStringList() << "Channel 1 主码流" );
    child1->addChild(child11);
    QTreeWidgetItem *child12 = new QTreeWidgetItem( QStringList() << "Channel 1 子码流" );
    child1->addChild(child12);

    // 顶层子节点的子节点的子节点
    QTreeWidgetItem *child21 = new QTreeWidgetItem( QStringList() << "主码流" );
    child2->addChild(child21);
    QTreeWidgetItem *child22 = new QTreeWidgetItem( QStringList() << "子码流" );
    child2->addChild(child22);

    ui->deviceTreeWidget->expandItem(netVideo); // 展开节点
    ui->deviceTreeWidget->expandItem(child1);
}

void MainWindow::insertMsg(const QString &message)
{
    int currentRowCount = ui->windowInfoTable->rowCount();

    // 如果表格未满，直接插入新行
    if (currentRowCount < 99) {
        ui->windowInfoTable->insertRow(0);
    }
    // 如果表格已满，删除最后一行，再插入到最前面
    else {
        ui->windowInfoTable->removeRow(99 - 1); // 删除第 99 行
        ui->windowInfoTable->insertRow(0);            // 在第 0 行插入
    }

    // 设置时间（第 0 列）
    QTime currentTime = QTime::currentTime();
    ui->windowInfoTable->setItem(0, 0, new QTableWidgetItem(currentTime.toString("hh:mm:ss")));

    // 设置消息（第 1 列）
    ui->windowInfoTable->setItem(0, 1, new QTableWidgetItem(message));
}



// === 回调实现 ===
void MainWindow::onClientConnected()
{
    insertMsg("已连接服务器");
}

void MainWindow::onClientDisconnected()
{
    insertMsg("与服务器断开");
}

void MainWindow::onMessageReceived(const QByteArray& message)
{
    QString str = message;
    qDebug() << "main message：" << str;
}

void MainWindow::onErrorOccurred(QAbstractSocket::SocketError err)
{
    insertMsg(QString("发生错误：%1").arg(static_cast<int>(err)));
}



void MainWindow::on_deviceTreeWidget_itemClicked(QTreeWidgetItem *item, int column)
{
    if (item->text(column) == "Channel 1 主码流") {
        nlohmann::json j;
        if(m_Channel_1_isPlay){
            // 如果正在播放，退出推流队列
            j["type"] = 105;
            j["data"]["account"] = g_account.toStdString ();

            QString jsonStr = QString::fromStdString (j.dump ());
            m_videoClient->sendMessage (jsonStr.toUtf8 ());

            m_lastFrame = QImage();
            ui->videoLabel1->clear();
            ui->videoLabel1->setText("通道1\n\n未连接");
            m_Channel_1_isPlay = false;
            insertMsg("停止播放实时流并清空缓冲");

        }else{
            // 未在播放，加入推流队列
            j["type"] = 104;
            j["data"]["account"] = g_account.toStdString ();

            QString jsonStr = QString::fromStdString (j.dump ());
            m_videoClient->sendMessage (jsonStr.toUtf8 ());
            m_Channel_1_isPlay = true;



            insertMsg("开始播放实时流");
        }


    } else if (item->text(column) == "Channel 1 子码流") {

    }

    // if( item->text (column) == "主码流" ){
    //     ui->videoLabel1->setText ("正在播放");
    //     m_playerCore->stopAsync ();
    //     m_playerCore->setMedia ("rtsp://admin:admin@192.168.106.222/live/chn=0"); // 设置要播放的文件
    //     m_playerCore->setVideoWidget ( ui->videoWidget1 ); // 设置要播放的widget
    //     m_playerCore->play (); // 开始播放

    // }else if( item->text (column) == "子码流" ){
    //     ui->videoLabel2->setText ("通道1\n未连接");
    //     m_playerCore->stopAsync ();
    // }
}

// 云台控制
void MainWindow::ptzControl(int position, const QString &name){

    Q_UNUSED(name);
    QString str = "http://192.168.106.222/xsw/api/ptz/control?";
    KVQuery kvs;
    kvs.add("value", positionMap[position]);

    str += QString::fromStdString(kvs.toCrpytString());

    QNetworkAccessManager *manager = new QNetworkAccessManager();
    QNetworkRequest request{QUrl(str)};  // 初始化请求

    // 添加 Content-Type 请求头
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

    QNetworkReply *reply = manager->get(request);
    QObject::connect(reply, &QNetworkReply::finished, [=]() {
        QString responseData(reply->readAll ());
        if( responseData == "{\"code\":0,\"msg\":\"\"}" ){
            insertMsg ("云台控制指令执行成功：" + positionMapS[position]);
        }else{
            insertMsg ("云台控制指令执行失败：" + responseData);
        }

        reply->deleteLater();
        manager->deleteLater();
    });


}


